#include <QApplication>
#include <QFile>
#include <QUrl>
#include "poststyle.h"
#include "log.h"
#include "chanmanager.h"

PostStyle::PostStyle() : QObject(),
	m_backgroundFile(0)
{
	loadDefaults();
	m_connector = new HttpConnector(this);
}

PostStyle::~PostStyle()
{
	if(m_backgroundFile)
		delete m_backgroundFile;
	delete m_connector;
}

void PostStyle::loadDefaults()
{
	m_backgroundColor = QColor(0xee, 0xee, 0xee);
	m_textColor = QColor(0x33, 0x33, 0x33);
	m_linkColor = QColor(0xff, 0x66, 0x00);
	m_linkHoverColor = QColor(0x00, 0x66, 0xff);
	m_postBackgroundColor = QColor(0xdd, 0xdd, 0xdd);
	m_postBorderColor = QColor(0xcc, 0xcc, 0xcc);
	m_postSelectedBorderColor = QColor(0xff, 0x66, 0x00);

	m_deleteIcon.load(":/wishmaster/images/delete2.png");
	m_deleteIcon = m_deleteIcon.scaled(QSize(16, 16), Qt::KeepAspectRatio, Qt::SmoothTransformation);
	m_hideIcon.load(":/wishmaster/images/zoom_out.png");
	m_hideIcon = m_hideIcon.scaled(QSize(16, 16), Qt::KeepAspectRatio, Qt::SmoothTransformation);
	m_unhideIcon.load(":/wishmaster/images/zoom_in.png");
	m_unhideIcon = m_unhideIcon.scaled(QSize(16, 16), Qt::KeepAspectRatio, Qt::SmoothTransformation);
	m_infoIcon.load(":/wishmaster/images/info.png");
	m_infoIcon = m_infoIcon.scaled(QSize(16, 16), Qt::KeepAspectRatio, Qt::SmoothTransformation);

	m_postFont = QFont(qApp->font());
	m_headerFont = QFont(qApp->font());
	m_noteFont = QFont(qApp->font());

	m_borderRadius = 1;
}

bool PostStyle::loadFromFile(const QString& filename)
{
	QFile f(filename);
	if(!f.open(QIODevice::ReadOnly))
		return false;
	m_filename = filename;
	return loadStyle(QString::fromUtf8(f.readAll()));
}

bool PostStyle::loadStyle(const QString& style)
{
	// TODO rewrite
	QString body = getSection(style, "body");
	if(!body.isEmpty())
	{
		QString background = getParam(body, "background");
		if(!background.isEmpty())
		{
			loadBackground(background);
		}
		setColorIfValid(m_backgroundColor, parseColor(getParam(body, "background-color")));
		setColorIfValid(m_textColor, parseColor(getParam(body, "color")));
		setColorIfValid(m_headerColor, parseColor(getParam(body, "color")));
	}

	QString a = getSection(style, "a");
	if(!a.isEmpty())
		setColorIfValid(m_linkColor, parseColor(getParam(a, "color")));

	QString ahover = getSection(style, "a:hover");
	if(!ahover.isEmpty())
		setColorIfValid(m_linkHoverColor, parseColor(getParam(ahover, "color")));

	QString reply = getSection(style, "reply");
	if(!reply.isEmpty())
	{
		//setColorIfValid(m_postBackgroundColor, parseColor(getParam(reply, "background")));
		setColorIfValid(m_postBackgroundColor, parseColor(getParam(reply, "background-color")));
		setColorIfValid(m_textColor, parseColor(getParam(reply, "color")));
		QString border = getParam(reply, "border");
		if(!border.isEmpty())
		{
			QStringList list = border.split(' ');
			foreach(const QString& s, list)
			{
				if(s.startsWith('#'))
				{
					setColorIfValid(m_postBorderColor, parseColor(s));
					break;
				}
			}
		}
		QString borderRadius = getParam(reply, "-webkit-border-radius");
		if(!borderRadius.isEmpty())
			m_borderRadius = borderRadius.left(borderRadius.indexOf("px")).toUInt();
	}

	QString replytitle = getSection(style, "replytitle");
	if(!replytitle.isEmpty())
	{
		setColorIfValid(m_headerColor, parseColor(getParam(replytitle, "color")));
	}

	return true;
}

void PostStyle::setColorIfValid(QColor& color, const QColor& newColor)
{
	if(newColor.isValid())
		color = newColor;
}

QString PostStyle::getSection(const QString& doc, const QString& tag)
{
	QRegExp rx(QString("\\b%1\\b[^{]*\\{\\s*([^}]*)\\s*\\}").arg(tag));
	if(rx.indexIn(doc) >= 0)
	{
		return rx.cap(1);
	}
	return QString::null;
}

QString PostStyle::getParam(const QString& section, const QString& param)
{
	int p = 0;
	while(p >= 0)
	{
		p = section.indexOf(param + ':', p + 1);
		if(p < 0)
			return QString::null;
		if((p != 0) && (section.at(p - 1) != '-'))
			break;
	}
	int semicolon = section.indexOf(';', p);
	if(semicolon < 0)
		return QString::null;
	int valuestart = p + param.length() + 1;
	QString value = section.mid(valuestart, semicolon - valuestart).trimmed();
	if(value.endsWith("!important"))
		value.chop(sizeof("!important"));
	return value;
}

QColor PostStyle::parseColor(const QString& color)
{
	if(color.isEmpty())
		return QColor();
	if(color.startsWith('#'))
	{
		int rgb = color.mid(1).toUInt(0, 16);
		return QColor((rgb >> 16) & 0xff, (rgb >> 8) & 0xff, (rgb >> 0) & 0xff);
	}
	return QColor(color);
}

void PostStyle::loadBackground(const QString& background)
{
	if(!m_connector)
		return;
	m_background.clear();
	QStringList list = background.split(' ');
	foreach(const QString& s, list)
	{
		if(s.startsWith("url(") && s.endsWith(')'))
		{
			QString picurl = s.mid(4, s.length() - 5);
			if(picurl.startsWith("http://"))
			{
				QUrl url(picurl);
				RequestPtr r = m_connector->makeRequest(url.host(), url.path(), "GET");
				connect(r.data(), SIGNAL(result(RequestPtr, QByteArray)), this, SLOT(backgroundImage(RequestPtr, QByteArray)));
				m_connector->queueFirst(r);
				m_backgroundFile = new QTemporaryFile();
				m_backgroundFile->open();
				m_background.append(QString("url(%1) ").arg(m_backgroundFile->fileName()));
			}
		}
	}
}

void PostStyle::backgroundImage(RequestPtr r, const QByteArray& arr)
{
	m_backgroundFile->write(arr);
}

QColor PostStyle::backgroundColor()
{
	return m_backgroundColor;
}

QColor PostStyle::headerColor()
{
	return m_headerColor;
}

QColor PostStyle::postBackgroundColor()
{
	return m_postBackgroundColor;
}

QColor PostStyle::postBorderColor()
{
	return m_postBorderColor;
}

QColor PostStyle::postSelectedBorderColor()
{
	return m_postSelectedBorderColor;
}

QColor PostStyle::textColor()
{
	return m_textColor;
}

QColor PostStyle::linkColor()
{
	return m_linkColor;
}

QColor PostStyle::linkHoverColor()
{
	return m_linkHoverColor;
}

QImage PostStyle::deleteIcon()
{
	return m_deleteIcon;
}

QImage PostStyle::hideIcon()
{
	return m_hideIcon;
}

QImage PostStyle::unhideIcon()
{
	return m_unhideIcon;
}


QImage PostStyle::infoIcon()
{
	return m_infoIcon;
}

void PostStyle::setPostFont(const QFont& f)
{
	m_postFont = f;
}

void PostStyle::setHeaderFont(const QFont& f)
{
	m_headerFont = f;
}

void PostStyle::setNoteFont(const QFont& f)
{
	m_noteFont = f;
}

QFont PostStyle::postFont()
{
	return m_postFont;
}

QFont PostStyle::headerFont()
{
	return m_headerFont;
}

QFont PostStyle::noteFont()
{
	return m_noteFont;
}

int PostStyle::borderRadius() const
{
	return m_borderRadius;
}

QString PostStyle::background() const
{
	return m_background;
}
